package com.gk.panda.apis.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gk.panda.apis.config.ElecRailConfig;
import com.gk.panda.apis.entity.elecRail.dto.ElecRailSearchDto;
import com.gk.panda.apis.entity.elecRail.dto.HeatMapDto;
import com.gk.panda.apis.entity.elecRail.dto.HeatMapGeoJsonDto;
import com.gk.panda.apis.entity.elecRail.entity.RegionalPersonCount;
import com.gk.panda.apis.entity.elecRail.vo.*;
import com.gk.panda.apis.mapper.ElecRailMapper;
import com.gk.panda.apis.service.*;
import com.gk.panda.apis.util.ElecRailUtils;
import com.gk.panda.commons.constant.Constants;
import com.gk.panda.commons.exception.ServerException;
import com.gk.panda.commons.util.http.HttpClientResult;
import com.gk.panda.commons.util.http.HttpClientUtils;
import com.gk.panda.pojo.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @ClassName: ElecRailService
 * @Description: 电子围栏接入
 * @author: wangchao
 * @date: 2022/11/14 10:04
 * @version: 1.0
 **/
@Service
public class ElecRailServiceImpl extends ServiceImpl<ElecRailMapper, ElecRail> implements ElecRailService {

    @Autowired
    private ElecRailConfig elecRailConfig;

    @Autowired
    private HeatMapDataService heatMapDataService;

    @Autowired
    private CrownMoveService crownMoveService;

    @Autowired
    private AreaUserCountService areaUserCountService;

    /**
     * @description: 调用电子围栏接口获取热力统计
     * @param: [areaCode：区域ID]
     * @param: [queryDate：查询时间，格式为：YYYYMMDDHH]
     * @return:
     * @date: 2022/11/14 10:05
     * @version: 1.0
     **/
    @Override
    public List<HeatMapVo> getRegionalHeat(String areaCode, String queryDate) throws Exception {
        String privateKey = elecRailConfig.getPrivateKey();
        String requestUrl = elecRailConfig.getRequestUrl();
        String xappid = elecRailConfig.getXAPPID();
        String xappkey = elecRailConfig.getXAPPKEY();
        String xctgversion = elecRailConfig.getXCTGVERSION();
        String tenantName = elecRailConfig.getTenantName();
        if (StringUtils.isEmpty(areaCode) || StringUtils.isEmpty(queryDate)) {
            throw new ServerException("调用电子围栏接口请求参数不能为空！");
        }
        Map<String, Object> data = new HashMap<>();//传入参数
        data.put("AREA_CODE", areaCode);
        data.put("QUERY_DATE", queryDate);
        data.put("METHOD_TYPE", "PANDA_PARK_REGIONAL_HEAT");
        String todoValue = JSON.toJSONString(data);
        String miValue = ElecRailUtils.encryptByPrivateKeyStr(todoValue, privateKey);//私加密
        HeatMapDto heatMapDto = new HeatMapDto();
        heatMapDto.setTENANT_NAME(tenantName);
        heatMapDto.setMI_VALUE(miValue);
        Map<String, String> headers = new HashMap<>();
        headers.put("X-APP-ID", xappid);
        headers.put("X-APP-KEY", xappkey);
        headers.put("X-CTG-VERSION", xctgversion);
        HttpClientResult httpClientResult = null;
        try {
            httpClientResult = HttpClientUtils.doPostJson(requestUrl, headers, JSONUtil.toJsonStr(heatMapDto));
        } catch (Exception e) {
            throw new ServerException("调用电子围栏接口失败");
        }
        if (Constants.SUCCESS != httpClientResult.getCode()) {
            throw new ServerException("调用电子围栏接口失败!");
        }
        List<HeatMapVo> heatMapVos = new ArrayList<>();
        HeatMapResultVo resultVo = JSON.parseObject(httpClientResult.getContent(), HeatMapResultVo.class);
        if (Constants.LOGIN_SUCCESS_STATUS.equals(resultVo.getResultCode())) {
            if (!resultVo.getInfo().equals("{}")) {
                ResultInfo info = JSON.parseObject(resultVo.getInfo(), ResultInfo.class);
                heatMapVos.addAll(info.getList());
            }
        }
        return heatMapVos;
    }

    /**
     * 调用区域人员移动接口获取某时刻某区域内人员移动情况
     *
     * @param areaCode：区域id
     * @param queryDate：查询时间 yyyMMddHH
     * @return
     * @throws Exception
     */
    @Override
    public List<CrownMoveVo> getCrownMoveData(String areaCode, String queryDate) throws Exception {
        String privateKey = elecRailConfig.getPrivateKey();
        String requestUrl = elecRailConfig.getRequestUrl();
        String xappid = elecRailConfig.getXAPPID();
        String xappkey = elecRailConfig.getXAPPKEY();
        String xctgversion = elecRailConfig.getXCTGVERSION();
        String tenantName = elecRailConfig.getTenantName();
        if (StringUtils.isEmpty(areaCode) || StringUtils.isEmpty(queryDate)) {
            throw new ServerException("调用电子围栏接口请求参数不能为空！");
        }
        Map<String, Object> data = new HashMap<>();//传入参数
        data.put("AREA_CODE", areaCode);
        data.put("QUERY_DATE", queryDate);
        data.put("METHOD_TYPE", "PANDA_PARK_CROWD_MOVE");
        String todoValue = JSON.toJSONString(data);
        String miValue = ElecRailUtils.encryptByPrivateKeyStr(todoValue, privateKey);//私加密
        HeatMapDto heatMapDto = new HeatMapDto();
        heatMapDto.setTENANT_NAME(tenantName);
        heatMapDto.setMI_VALUE(miValue);
        Map<String, String> headers = new HashMap<>();
        headers.put("X-APP-ID", xappid);
        headers.put("X-APP-KEY", xappkey);
        headers.put("X-CTG-VERSION", xctgversion);
        HttpClientResult httpClientResult = null;
        try {
            httpClientResult = HttpClientUtils.doPostJson(requestUrl, headers, JSONUtil.toJsonStr(heatMapDto));
        } catch (Exception e) {
            throw new ServerException("调用电子围栏接口失败");
        }
        if (Constants.SUCCESS != httpClientResult.getCode()) {
            throw new ServerException("调用电子围栏接口失败!");
        }
        List<CrownMoveVo> crownMoveVos = new ArrayList<>();
        HeatMapResultVo resultVo = JSON.parseObject(httpClientResult.getContent(), HeatMapResultVo.class);
        if (Constants.LOGIN_SUCCESS_STATUS.equals(resultVo.getResultCode())) {
            if (!resultVo.getInfo().equals("{}")) {
                CrownMoveResultInfo info = JSON.parseObject(resultVo.getInfo(), CrownMoveResultInfo.class);
                crownMoveVos.addAll(info.getList());
            }
        }
        return crownMoveVos;
    }

    /**
     * 获取某时刻多个区域内的热力图geoJson数据
     *
     * @param dto
     * @return
     * @throws Exception
     */
    @Override
    public List<GeoJson> RegionalHeatOfGIS(HeatMapGeoJsonDto dto) throws Exception {
        List<String> areaCodes = dto.getAreaCodes();
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中的小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 3);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHH");
        String queryDate = dto.getQueryDate();
        if (StringUtils.isBlank(queryDate)) {
            queryDate = df.format(calendar.getTime());
        }
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        String lastQueryDate = nf.format(Double.parseDouble(queryDate) - 1);
        if (areaCodes == null || areaCodes.size() == 0) {
            areaCodes = Arrays.asList("C1", "C2", "C3", "C4", "C5", "C6", "G1", "G2", "G3", "G4", "G5", "G6");
        }
        List<GeoJson> geoJsons = new ArrayList<>();
        QueryWrapper<HeatMapData> wrapper = new QueryWrapper<>();
        for (String areaCode : areaCodes) {
            wrapper.clear();
            wrapper.eq("time", queryDate);
            wrapper.eq("area_code", areaCode);
            HeatMapData heatMapData = heatMapDataService.getOne(wrapper);
            if (heatMapData != null) {
                String geoJson = heatMapData.getGeoJson();
                if (!geoJson.equals("[]")) {
                    List<GeoJson> dataList = JSON.parseArray(geoJson, GeoJson.class);
                    geoJsons.addAll(dataList);
                }
            } else {
                List<HeatMapVo> heatMapVos = getRegionalHeat(areaCode, queryDate);
                if (heatMapVos != null && heatMapVos.size() > 0) {
                    for (HeatMapVo heatMapVo : heatMapVos) {
                        List<Double> coordinates = new ArrayList<>();
                        coordinates.add(Double.valueOf(heatMapVo.getLON()));
                        coordinates.add(Double.valueOf(heatMapVo.getLAT()));
                        GeoJson geoJson = new GeoJson();
                        Map<String, Object> geometry = new HashMap<>();
                        geometry.put("type", "Point");
                        geometry.put("coordinates", coordinates);
                        geoJson.setGeometry(geometry);
                        //基数
                        double cardinality = 100;
                        double mag = Integer.parseInt(heatMapVo.getUSER_CNT()) / cardinality;
                        Map<String, Object> Properties = new HashMap<>();
                        Properties.put("mag", mag);
                        Properties.put("personNum", heatMapVo.getUSER_CNT());
                        Properties.put("time", queryDate);
                        geoJson.setProperties(Properties);
                        geoJsons.add(geoJson);
                    }
                } else {
                    wrapper.clear();
                    wrapper.eq("time", lastQueryDate);
                    wrapper.eq("area_code", areaCode);
                    heatMapData = heatMapDataService.getOne(wrapper);
                    if (heatMapData != null) {
                        String geoJson = heatMapData.getGeoJson();
                        List<GeoJson> dataList = JSON.parseArray(geoJson, GeoJson.class);
                        geoJsons.addAll(dataList);
                    }
                }
            }
        }
        return geoJsons;
    }

    /**
     * 分页查询电子围栏数据
     *
     * @param dto : 电子围栏查询类
     * @return
     */
    @Override
    public Page<ElecRail> getElecRailList(ElecRailSearchDto dto) {
        Page<ElecRail> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        QueryWrapper<ElecRail> wrapper = new QueryWrapper<>();
        if (dto.getOrgIds() != null && dto.getOrgIds().size() > 0) {
            wrapper.in("org_id", dto.getOrgIds());
        }
        if (dto.getIsCore() != null) {
            wrapper.eq("is_core", dto.getIsCore());

        }
        wrapper.gt(dto.getStartTime() != null, "create_time", dto.getStartTime());
        wrapper.lt(dto.getEndTime() != null, "create_time", dto.getEndTime());
        wrapper.eq("del_flag", 0);
        wrapper.orderByDesc("create_time");
        return this.page(page, wrapper);
    }

    /**
     * 获取热力图区域人数统计
     *
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getRegionalPersonCount() throws Exception {
        Map<String, Object> personCountMap = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中的小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 3);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHH");
        String queryDateNow = df.format(calendar.getTime());

        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        String queryDatePrev = df.format(calendar.getTime());

        RegionalPersonCount personCountNow = getPersonCountByTime(queryDateNow);
        if (personCountNow.getCoreNum() == 0) {
            personCountNow = getPersonCountByTime(queryDatePrev);
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
            queryDatePrev = df.format(calendar.getTime());
            RegionalPersonCount personCountPrev = getPersonCountByTime(queryDatePrev);
            personCountMap.put("collectTime", queryDatePrev);
            personCountMap.put("personCountNow", personCountNow);
            personCountMap.put("personCountPrev", personCountPrev);
        } else {
            RegionalPersonCount personCountPrev = getPersonCountByTime(queryDatePrev);
            personCountMap.put("collectTime", queryDateNow);
            personCountMap.put("personCountNow", personCountNow);
            personCountMap.put("personCountPrev", personCountPrev);
        }
        return personCountMap;
    }

    /**
     * 通过时间查热力图人数统计
     *
     * @param queryDate
     * @return
     * @throws Exception
     */
    public RegionalPersonCount getPersonCountByTime(String queryDate) throws Exception {
        List<String> coreAreaCodes = Arrays.asList("C1", "C2", "C3", "C4", "C5", "C6");
        List<String> generalAreaCodes = Arrays.asList("G1", "G2", "G3", "G4", "G5", "G6");
        List<HeatMapVo> coreHeatMapVos = new ArrayList<>();
        for (String coreAreaCode : coreAreaCodes) {
            coreHeatMapVos.addAll(getRegionalHeat(coreAreaCode, queryDate));
        }
        int coreNum = 0;
        for (HeatMapVo coreHeatMapVo : coreHeatMapVos) {
            coreNum += Integer.parseInt(coreHeatMapVo.getUSER_CNT());
        }
        List<HeatMapVo> generalHeatMapVos = new ArrayList<>();
        for (String generalAreaCode : generalAreaCodes) {
            generalHeatMapVos.addAll(getRegionalHeat(generalAreaCode, queryDate));
        }
        int generalNum = 0;
        for (HeatMapVo generalHeatMapVo : generalHeatMapVos) {
            generalNum += Integer.parseInt(generalHeatMapVo.getUSER_CNT());
        }
        RegionalPersonCount regionalPersonCount = new RegionalPersonCount();
        regionalPersonCount.setCoreNum(coreNum);
        regionalPersonCount.setGeneralNum(generalNum);
        regionalPersonCount.setCount(coreNum + generalNum);
        return regionalPersonCount;
    }

    /**
     * 获取热力图人员移动geoJson数据
     *
     * @param dto
     * @return
     * @throws Exception
     */
    @Override
    public List<GeoJson> getCrowdMove(HeatMapGeoJsonDto dto) throws Exception {
        List<String> areaCodes = dto.getAreaCodes();
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中的小时 */
        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 1);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHH");
        String queryDate = df.format(calendar.getTime());
        List<GeoJson> geoJsons = new ArrayList<>();
        if (areaCodes == null || areaCodes.size() == 0) {
            areaCodes = Arrays.asList("C1", "C2", "C3", "C4", "C5", "C6", "G1", "G2", "G3", "G4", "G5", "G6");
        }
        QueryWrapper<CrownMove> wrapper = new QueryWrapper<>();
        wrapper.in("area_code", areaCodes)
                .gt("quarter_no", queryDate)
                .orderByAsc("quarter_no");
        List<CrownMove> crownMoves = crownMoveService.list(wrapper);
        Map<String, List<CrownMove>> map = crownMoves.stream().collect(Collectors.groupingBy(CrownMove::getUserId));
        for (Map.Entry<String, List<CrownMove>> entry : map.entrySet()) {
            String userId = entry.getKey();
            List<CrownMove> crownMoveList = entry.getValue();
            //少于3个点的不返回
            if (crownMoveList.size() < 3) continue;
            CrownMove first = crownMoveList.get(0);
            CrownMove last = crownMoveList.get(crownMoveList.size() - 1);
            double firstLot = Double.parseDouble(first.getLot());
            double firstLat = Double.parseDouble(first.getLat());
            double lastLot = Double.parseDouble(last.getLot());
            double lastLat = Double.parseDouble(last.getLat());
            double differLot = firstLot - lastLot;
            double differLat = firstLat - lastLat;
            double length = Math.sqrt(Math.pow((differLot) * 111, 2) + Math.pow((differLat) * 111, 2));
            //轨迹长度少于3KM的不要
            if (length < 3) continue;
            GeoJson geoJson = new GeoJson();
            List<List<Double>> coordinates = new ArrayList<>();
//            Iterator<CrownMove> iterator = crownMoveList.iterator();
//            while (iterator.hasNext()) {
//                CrownMove crownMove = iterator.next();
//                int index = crownMoveList.indexOf(crownMove);
//                if (index != 0) {
//                    CrownMove last = crownMoveList.get(index - 1);
//                    double lot = Double.parseDouble(crownMove.getLot());
//                    double lat = Double.parseDouble(crownMove.getLat());
//                    double lastLot = Double.parseDouble(last.getLot());
//                    double lastLat = Double.parseDouble(last.getLat());
//                    double differLot = lot - lastLot;
//                    double differLat = lat - lastLat;
//                    if (differLot == 0 && differLat == 0) {
//                        iterator.remove();
//                        continue;
//                    }
//                }
            for (CrownMove crownMove : crownMoveList) {
                List<Double> coordinate = new ArrayList<>();
                coordinate.add(Double.valueOf(crownMove.getLot()));
                coordinate.add(Double.valueOf(crownMove.getLat()));
                coordinates.add(coordinate);
            }
            Map<String, Object> geometry = new HashMap<>();
            geometry.put("type", "LineString");
            geometry.put("coordinates", coordinates);
            geoJson.setGeometry(geometry);

            Map<String, Object> Properties = new HashMap<>();
            Properties.put("userId", userId);
            geoJson.setProperties(Properties);
            geoJsons.add(geoJson);
        }
        return geoJsons;
    }

    /**
     * 存储人员移动数据
     *
     * @throws Exception
     */
    @Override
    public void saveCrownMoveData() throws Exception {
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中的小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 3);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHH");
        String queryDate = df.format(calendar.getTime());
        List<String> areaCodes = Arrays.asList("C1", "C2", "C3", "C4", "C5", "C6"
                , "G1", "G2", "G3", "G4", "G5", "G6"
        );
        List<CrownMove> crownMoves = new ArrayList<>();
        for (String areaCode : areaCodes) {
            List<CrownMoveVo> crownMoveVos = getCrownMoveData(areaCode, queryDate);
            for (CrownMoveVo crownMoveVo : crownMoveVos) {
                CrownMove crownMove = new CrownMove();
                crownMove.setLot(crownMoveVo.getLON());
                crownMove.setLat(crownMoveVo.getLAT());
                crownMove.setQuarterNo(crownMoveVo.getQUARTER_NO());
                crownMove.setUserId(crownMoveVo.getUSER_ID());
                crownMove.setAreaCode(areaCode);
                crownMoves.add(crownMove);
            }
        }
        if (crownMoves.size() == 0) return;
        Map<String, List<CrownMove>> map = crownMoves.stream().collect(Collectors.groupingBy(CrownMove::getUserId));
        List<List<CrownMove>> values = new ArrayList<>(map.values());
        Set<String> userIds = map.keySet();
        List<CrownMove> list = crownMoveService.getLastByUserIds(userIds);
        List<String> ids = list.stream().map(CrownMove::getUserId).collect(Collectors.toList());
        Map<String, List<CrownMove>> collect = list.stream().collect(Collectors.groupingBy(CrownMove::getUserId));
        List<CrownMove> newCrownMoves = new ArrayList<>();
        for (List<CrownMove> value : values) {
            value.sort(Comparator.comparing(CrownMove::getQuarterNo));
            Iterator<CrownMove> iterator = value.iterator();
            while (iterator.hasNext()) {
                CrownMove crownMove = iterator.next();
                int index = value.indexOf(crownMove);
                CrownMove last;
                if (index == 0 && ids.contains(crownMove.getUserId())) {
                    last = collect.get(crownMove.getUserId()).get(0);
                } else if (index != 0) {
                    last = value.get(index - 1);
                } else continue;
                double lot = Double.parseDouble(crownMove.getLot());
                double lat = Double.parseDouble(crownMove.getLat());
                double lastLot = Double.parseDouble(last.getLot());
                double lastLat = Double.parseDouble(last.getLat());
                double differLot = lot - lastLot;
                double differLat = lat - lastLat;
                if (differLot == 0 && differLat == 0) {
                    iterator.remove();
                    continue;
                }
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
                Date quarterNo = sdf.parse(crownMove.getQuarterNo());
                Date lastQuarterNo = sdf.parse(last.getQuarterNo());
                long time1 = quarterNo.getTime();
                long time2 = lastQuarterNo.getTime();
                long num = (time1 - time2) / 60000;
                if (Math.sqrt(Math.pow((differLot) * 111, 2) + Math.pow((differLat) * 111, 2)) > 0.02 * num) {
                    iterator.remove();
                }
            }
            newCrownMoves.addAll(value);
        }
        crownMoveService.saveBatch(newCrownMoves);
    }

    /**
     * 删除人员移动数据
     *
     * @param queryDate
     */
    @Override
    public void removeCrownMoveData(String queryDate) {
        QueryWrapper<CrownMove> wrapper = new QueryWrapper<>();
        wrapper.lt("quarter_no", queryDate);
        crownMoveService.remove(wrapper);
    }

    /**
     * 存储热力图geoJson数据
     *
     * @throws Exception
     */
    @Override
    public void saveHeatMapData() throws Exception {
        List<String> areaCodes = Arrays.asList("C1", "C2", "C3", "C4", "C5", "C6", "G1", "G2", "G3", "G4", "G5", "G6");
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中的小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 3);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHH");
        String queryDate = df.format(calendar.getTime());
        for (String areaCode : areaCodes) {
            List<GeoJson> geoJsons = new ArrayList<>();
            List<HeatMapVo> heatMapVos = getRegionalHeat(areaCode, queryDate);
            for (HeatMapVo heatMapVo : heatMapVos) {
                List<Double> coordinates = new ArrayList<>();
                coordinates.add(Double.valueOf(heatMapVo.getLON()));
                coordinates.add(Double.valueOf(heatMapVo.getLAT()));
                GeoJson geoJson = new GeoJson();
                Map<String, Object> geometry = new HashMap<>();
                geometry.put("type", "Point");
                geometry.put("coordinates", coordinates);
                geoJson.setGeometry(geometry);
                //基数
                double cardinality = 100;
                double mag = Integer.parseInt(heatMapVo.getUSER_CNT()) / cardinality;
                Map<String, Object> Properties = new HashMap<>();
                Properties.put("mag", mag);
                Properties.put("personNum", heatMapVo.getUSER_CNT());
                Properties.put("time", queryDate);
                geoJson.setProperties(Properties);
                geoJsons.add(geoJson);
            }
            if (geoJsons.size() > 0) {
                String geoJson = JSON.toJSONString(geoJsons);
                HeatMapData heatMapData = new HeatMapData();
                heatMapData.setGeoJson(geoJson);
                heatMapData.setTime(queryDate);
                heatMapData.setAreaCode(areaCode);
                heatMapData.setGeoJson(geoJson);
                heatMapDataService.save(heatMapData);
            }
        }

    }

    @Override
    public void savePersonCountOfDay() throws Exception {
        List<String> coreAreaCodes = Arrays.asList("C1", "C2", "C3", "C4", "C5", "C6");
        List<String> generalAreaCodes = Arrays.asList("G1", "G2", "G3", "G4", "G5", "G6");
        savePersonCountOfDayByAreaType(coreAreaCodes, "core");
        savePersonCountOfDayByAreaType(generalAreaCodes, "general");
    }

    private void savePersonCountOfDayByAreaType(List<String> areaCodes, String type) throws Exception {
        List<CrownMoveVo> coreCrownMoveVos = new ArrayList<>();
        List<String> times = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHH");
        for (int i = 0; i < 12; i++) {
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - (i + 3));
            times.add(df.format(calendar.getTime()));
        }
        for (String areaCode : areaCodes) {
            for (String time : times) {
                List<CrownMoveVo> crownMoveData = getCrownMoveData(areaCode, time);
                coreCrownMoveVos.addAll(crownMoveData);
            }
        }
        List<String> userIdsData = coreCrownMoveVos.stream().map(CrownMoveVo::getUSER_ID).collect(Collectors.toList());
        List<String> userIds = userIdsData.stream().distinct().collect(Collectors.toList());
        AreaUserCount areaUserCount = new AreaUserCount();
        areaUserCount.setAreaType(type);
        areaUserCount.setNum(userIds.size());
        String str = times.get(1);
        areaUserCount.setTime(str.substring(0, str.length() - 2));
        areaUserCountService.save(areaUserCount);
    }
}

